package com.ccjt.eip.web.util;

import com.ccjt.eip.web.mybatis.po.InformationSchema;
import com.google.common.base.Splitter;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.io.File;
import java.io.FileWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/*
* DBUtils代码生成类
* @author jiangpc
* @date 2019/06/26 11:12
* @param 
* @return 
*/
public class DBUtilCodeFactory {
    /*
     * 实体类创建
     * 
     * @author jiangpc
     * 
     * @date 2019/06/26 14:39
     * 
     * @param [FileFullPath, tableName, informationSchemas]
     * 
     * @return void
     */
    public static void createVo(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/Vo.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + conversionTableName + ".java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("creatTime", LocalDateTime.now());
            context.put("tableName", tableName);
            context.put("voEntity", conversionTableName);
            context.put("voParamaterEntity", entity.get("voParamaterEntity"));
            context.put("voParamaterGetSetEntity", entity.get("voParamaterGetSetEntity"));
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void createEsModel(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/EsModel.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEsEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + conversionTableName + ".java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("creatTime", LocalDateTime.now());
            context.put("tableName", tableName);
            context.put("voEntity", conversionTableName);
            context.put("voParamaterEntity", entity.get("voParamaterEntity"));
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /* 生成符合elementsui-admin的页面文件 */
    public static void createVueManage(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/vue/manage.vue", "UTF-8");
            File file = null;
            Map<String, String> entity = getVueManageEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + conversionTableName + ".vue");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("tableColumnsEntity", entity.get("tableColumnsEntity"));
            context.put("formFieldsEntity", entity.get("formFieldsEntity"));
            context.put("editFormFieldsEntity", entity.get("editFormFieldsEntity"));
            context.put("initEditFormDataEntity", entity.get("initEditFormDataEntity"));
            context.put("saveFormDataEntity", entity.get("saveFormDataEntity"));
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * dao层接口
     */
    public static void createDao(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/VoDao.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + "I" + conversionTableName + "Dao.java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("voEntity", conversionTableName);
            context.put("voEntityLowCase", entity.get("voEntityLowCase"));
            context.put("creatTime", LocalDateTime.now());
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * dao层实现类
     */
    public static void createDaoImpl(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/VoDaoImpl.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + conversionTableName + "DaoImpl.java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("tableName", tableName);
            context.put("voEntity", conversionTableName);
            context.put("voEntityLowCase", entity.get("voEntityLowCase"));
            context.put("creatTime", LocalDateTime.now());
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * 接口类创建
     * 
     * @author jiangpc
     * 
     * @date 2019/06/26 15:49
     * 
     * @param [FileFullPath, tableName, informationSchemas]
     * 
     * @return void
     */
    public static void createService(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/VoService.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + "I" + conversionTableName + "Service.java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("voEntity", conversionTableName);
            context.put("voEntityLowCase", entity.get("voEntityLowCase"));
            context.put("creatTime", LocalDateTime.now());
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * 接口实现类创建
     * 
     * @author jiangpc
     * 
     * @date 2019/06/26 15:48
     * 
     * @param [FileFullPath, tableName, informationSchemas]
     * 
     * @return void
     */
    public static void createServiceImpl(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/VoServiceImpl.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + conversionTableName + "ServiceImpl.java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("tableName", tableName);
            context.put("voEntity", conversionTableName);
            context.put("voEntityLowCase", entity.get("voEntityLowCase"));
            context.put("creatTime", LocalDateTime.now());
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * controller类实现
     * 
     * @author jiangpc
     * 
     * @date 2019/06/27 14:00
     * 
     * @param [FileFullPath, tableName, informationSchemas]
     * 
     * @return void
     */
    public static void createController(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/VoController.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + conversionTableName + "Controller.java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("voEntity", conversionTableName);
            context.put("voEntityLowCase", entity.get("voEntityLowCase"));
            context.put("creatTime", LocalDateTime.now());
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void createVueForm(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/VoForm.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + conversionTableName + "Form.java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("voEntity", conversionTableName);
            context.put("voEntityLowCase", entity.get("voEntityLowCase"));
            context.put("creatTime", LocalDateTime.now());
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /* mybatis bean */
    public static void createMpBean(String FileFullPath, String tableName, List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/mybatis/Bean.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getMpBean(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + conversionTableName + ".java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("creatTime", LocalDateTime.now());
            context.put("tableName", tableName);
            context.put("voEntity", conversionTableName);
            context.put("voParamaterEntity", entity.get("voParamaterEntity"));
            context.put("voParamaterGetSetEntity", entity.get("voParamaterGetSetEntity"));
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /* mybatis mapper class */
    public static void createMpInterface(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/mybatis/Mapper.java", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + "I" + conversionTableName + "Mapper.java");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("voEntity", conversionTableName);
            context.put("voEntityLowCase", entity.get("voEntityLowCase"));
            context.put("creatTime", LocalDateTime.now());
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /* mybatis mapper xml */
    public static void createMpXml(String FileFullPath, String tableName,
            List<InformationSchema> informationSchemas) {
        try {
            Template template = Velocity.getTemplate("/CodeTemplates/mybatis/Mapper.xml", "UTF-8");
            File file = null;
            Map<String, String> entity = getEntity(tableName, informationSchemas);
            String conversionTableName = entity.get("voEntity");
            file = new File(FileFullPath + "" + conversionTableName + "Mapper.xml");
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            System.out.println(file.getAbsolutePath());
            FileWriter fileWriter = new FileWriter(file);
            VelocityContext context = new VelocityContext();
            context.put("voEntity", conversionTableName);
            context.put("voEntityLowCase", entity.get("voEntityLowCase"));
            context.put("creatTime", LocalDateTime.now());
            template.merge(context, fileWriter);
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /* 获取mybatis参数 */
    private static Map<String, String> getMpBean(String tableName, List<InformationSchema> informationSchemas) {
        Map<String, String> map = new HashMap<>();
        StringBuilder voParamaterEntity = new StringBuilder();
        StringBuilder voParamaterGetSetEntity = new StringBuilder();
        String[] ts = tableName.split("_");
        StringBuilder conversionTableName = new StringBuilder();
        for (String t : ts) {
            conversionTableName.append(t.substring(0, 1).toUpperCase() + t.substring(1));
        }
        // String poIDName = "";
        // String tableIDName = "";
        // String poIDType = "";
        for (int i = 0; i < informationSchemas.size(); i++) {
            StringBuilder columnName = new StringBuilder();
            String cn = informationSchemas.get(i).getColumnName();
            String[] cs = cn.split("_");
            for (int j = 0; j < cs.length; j++) {
                if (j == 0) {
                    columnName.append(cs[j]);
                } else {
                    columnName.append(cs[j].substring(0, 1).toUpperCase()).append(cs[j].substring(1));
                }
            }
            String voDataType = formatSqlParamater(informationSchemas.get(i).getDataType());
            // if(i==0){
            // poIDName = columnName.toString();
            // tableIDName = cn;
            // poIDType = voDataType;
            // }
            if (cn.equals("id")) {
                voParamaterEntity.append("    /*").append(informationSchemas.get(i).getColumnComment() + "*/\n")
                        .append("    @TableId(type = IdType.AUTO)\n")
                        .append("    private ").append(voDataType + " ").append(columnName + ";\n");
            } else {
                voParamaterEntity.append("    /*").append(informationSchemas.get(i).getColumnComment() + "*/\n")
                        .append("    @TableField(value = \"" + cn + "\")\n")
                        .append("    private ").append(voDataType + " ").append(columnName + ";\n");
            }
            voParamaterGetSetEntity.append("    public ").append(voDataType + " ")
                    .append("get" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1)
                            + "() {\n        return ")
                    .append(columnName + ";\n    }").append("\n    public " + " void" + " ")
                    .append("set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1) + "(")
                    .append(voDataType + " ").append(columnName + ") {\n")
                    .append("        this." + columnName + " = " + columnName + ";\n            }\n");
        }
        map.put("voParamaterEntity", voParamaterEntity.toString());
        map.put("voParamaterGetSetEntity", voParamaterGetSetEntity.toString());
        map.put("voEntity", conversionTableName.toString());
        map.put("voEntityLowCase", conversionTableName.toString().substring(0, 1).toLowerCase()
                + conversionTableName.toString().substring(1));
        return map;
    }

    private static Map<String, String> getEntity(String tableName, List<InformationSchema> informationSchemas) {
        Map<String, String> map = new HashMap<>();
        StringBuilder voParamaterEntity = new StringBuilder();
        StringBuilder voParamaterGetSetEntity = new StringBuilder();
        String[] ts = tableName.split("_");
        StringBuilder conversionTableName = new StringBuilder();
        for (String t : ts) {
            conversionTableName.append(t.substring(0, 1).toUpperCase() + t.substring(1));
        }
        // String poIDName = "";
        // String tableIDName = "";
        // String poIDType = "";
        for (int i = 0; i < informationSchemas.size(); i++) {
            StringBuilder columnName = new StringBuilder();
            String cn = informationSchemas.get(i).getColumnName();
            String[] cs = cn.split("_");
            for (int j = 0; j < cs.length; j++) {
                if (j == 0) {
                    columnName.append(cs[j]);
                } else {
                    columnName.append(cs[j].substring(0, 1).toUpperCase()).append(cs[j].substring(1));
                }
            }
            String voDataType = formatSqlParamater(informationSchemas.get(i).getDataType());
            // if(i==0){
            // poIDName = columnName.toString();
            // tableIDName = cn;
            // poIDType = voDataType;
            // }
            if (cn.equals("id")) {
                voParamaterEntity.append("    //").append(informationSchemas.get(i).getColumnComment() + "\n")
                        .append("    @TableField(name=\"" + cn + "\",increment = true)\n")
                        .append("    private ").append(voDataType + " ").append(columnName + ";\n");
            } else {
                voParamaterEntity.append("    //").append(informationSchemas.get(i).getColumnComment() + "\n")
                        .append("    @TableField(name=\"" + cn + "\")\n")
                        .append("    private ").append(voDataType + " ").append(columnName + ";\n");
            }
            voParamaterGetSetEntity.append("    public ").append(voDataType + " ")
                    .append("get" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1)
                            + "() {\n        return ")
                    .append(columnName + ";\n    }").append("\n    public " + " void" + " ")
                    .append("set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1) + "(")
                    .append(voDataType + " ").append(columnName + ") {\n")
                    .append("        this." + columnName + " = " + columnName + ";\n            }\n");
        }
        map.put("voParamaterEntity", voParamaterEntity.toString());
        map.put("voParamaterGetSetEntity", voParamaterGetSetEntity.toString());
        map.put("voEntity", conversionTableName.toString());
        map.put("voEntityLowCase", conversionTableName.toString().substring(0, 1).toLowerCase()
                + conversionTableName.toString().substring(1));
        return map;
    }

    private static Map<String, String> getEsEntity(String tableName,
            List<InformationSchema> informationSchemas) {
        Map<String, String> map = new HashMap<>();
        StringBuilder voParamaterEntity = new StringBuilder();
        StringBuilder voParamaterGetSetEntity = new StringBuilder();
        String[] ts = tableName.split("_");
        StringBuilder conversionTableName = new StringBuilder();
        for (String t : ts) {
            conversionTableName.append(t.substring(0, 1).toUpperCase() + t.substring(1));
        }
        for (int i = 0; i < informationSchemas.size(); i++) {
            StringBuilder columnName = new StringBuilder();
            String cn = informationSchemas.get(i).getColumnName();
            columnName.append(cn);
            String voDataType = formatSqlParamater(informationSchemas.get(i).getDataType());
            if (cn.equals("id")) {
                voParamaterEntity
                        // .append(" @Id\n")
                        .append("    private ").append(voDataType + " ").append(columnName + ";\n");
            } else {
                voParamaterEntity
                        .append("    private ").append(voDataType + " ").append(columnName + ";\n");
            }
        }
        map.put("voParamaterEntity", voParamaterEntity.toString());
        map.put("voEntity", conversionTableName.toString());
        return map;
    }

    private static Map<String, String> getVueManageEntity(String tableName,
            List<InformationSchema> informationSchemas) {
        Map<String, String> map = new HashMap<>();
        StringBuilder tableColumnsEntity = new StringBuilder();
        StringBuilder formFieldsEntity = new StringBuilder();
        StringBuilder editFormFieldsEntity = new StringBuilder();
        StringBuilder initEditFormDataEntity = new StringBuilder();
        StringBuilder saveFormDataEntity = new StringBuilder();

        String[] ts = tableName.split("_");
        StringBuilder conversionTableName = new StringBuilder();
        for (String t : ts) {
            conversionTableName.append(t.substring(0, 1).toUpperCase() + t.substring(1));
        }
        for (int i = 0; i < informationSchemas.size(); i++) {
            String columnName = informationSchemas.get(i).getColumnName();// 字段名
            String coiumnNameOfHump = namingOfHump(columnName);//驼峰命名
            String voDataType = formatSqlParamater(informationSchemas.get(i).getDataType());// 类型
            if (columnName.equals("id")) {
                //
            } else {
                String tableColumnHtml = "      <el-table-column label=\"" + coiumnNameOfHump + "\">\r\n" + //
                        "        <template slot-scope=\"scope\">\r\n" + //
                        "          <span>{{ scope.row." + coiumnNameOfHump + " }}</span>\r\n" + //
                        "        </template>\r\n" + //
                        "      </el-table-column>";
                tableColumnsEntity.append(tableColumnHtml).append("\n");

                String formFieldsHtml = "        <el-form-item label=\"" + coiumnNameOfHump + "\">\r\n" + //
                                        "          <el-input v-model=\"editForm." + coiumnNameOfHump + "\" />\r\n" + //
                                        "        </el-form-item>";
                formFieldsEntity.append(formFieldsHtml).append("\n");

                String editFormFieldHtml = "        ".concat(coiumnNameOfHump).concat(": '',");
                editFormFieldsEntity.append(editFormFieldHtml).append("\n");

                String initEditFormDataHtml = "      this.editForm." + coiumnNameOfHump + " = row." + coiumnNameOfHump;
                initEditFormDataEntity.append(initEditFormDataHtml).append("\n");

                String saveFormDataHtml = "      formData.append('" + coiumnNameOfHump + "', this.editForm." + coiumnNameOfHump + ")";
                saveFormDataEntity.append(saveFormDataHtml).append("\n");
            }
        }
        map.put("voEntity", conversionTableName.toString());
        map.put("tableColumnsEntity", tableColumnsEntity.toString());
        map.put("formFieldsEntity", formFieldsEntity.toString());
        map.put("editFormFieldsEntity", editFormFieldsEntity.toString());
        map.put("initEditFormDataEntity", initEditFormDataEntity.toString());
        map.put("saveFormDataEntity", saveFormDataEntity.toString());
        return map;
    }
    /* 转驼峰命名 */
    private static String namingOfHump(String oldName){
        String[] ts = oldName.split("_");
        StringBuilder sb = new StringBuilder(ts[0]);
        for (int i = 1; i < ts.length; i++) {
            sb.append(ts[i].substring(0, 1).toUpperCase()).append(ts[i].substring(1));
        }
        return sb.toString();
    }

    private static String formatSqlParamater(String sqlParamater) {
        String paramater = "";
        switch (sqlParamater) {
            case "int":
                paramater = "Integer";
                break;
            case "bit":
                paramater = "Integer";
                break;
            case "tinyint":
                paramater = "Integer";
                break;
            case "bigint":
                paramater = "Long";
                break;
            case "varchar":
                paramater = "String";
                break;
            case "text":
                paramater = "String";
                break;
            case "longtext":
                paramater = "String";
                break;
            case "datetime":
                paramater = "Date";
                break;
            case "decimal":
                paramater = "BigDecimal";
                break;
            case "timestamp":
                paramater = "Date";
                break;
        }
        return paramater;
    }

}
